home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / ICMPCMD.C < prev    next >
Text File  |  1990-06-06  |  5KB  |  254 lines

  1. /* ICMP-related user commands */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "icmp.h"
  5. #include "mbuf.h"
  6. #include "netuser.h"
  7. #include "internet.h"
  8. #include "timer.h"
  9. #include "ping.h"
  10.  
  11. extern char nospace[];
  12. extern char badhost[];
  13.  
  14. int
  15. doicmpstat()
  16. {
  17.     extern struct icmp_errors icmp_errors;
  18.     extern struct icmp_stats icmp_stats;
  19.     extern char *icmptypes[];
  20.     register int i;
  21.  
  22.     printf("ICMP: chksum err %u no space %u icmp %u bdcsts %u\n",
  23.      icmp_errors.checksum,icmp_errors.nospace,icmp_errors.noloop,
  24.      icmp_errors.bdcsts);
  25.     printf("type  rcvd  sent\n");
  26.     for(i=0;i<ICMP_TYPES;i++){
  27.         if(icmp_stats.input[i] == 0 && icmp_stats.output[i] == 0)
  28.             continue;
  29.         printf("%-6u%-6u%-6u",i,icmp_stats.input[i],
  30.             icmp_stats.output[i]);
  31.         if(icmptypes[i] != NULLCHAR)
  32.             printf("  %s",icmptypes[i]);
  33.         printf("\n");
  34.     }
  35.     return 0;
  36. }
  37.  
  38. /* Hash table list heads */
  39. struct ping *ping[PMOD];
  40.  
  41. /* Length of ping packets (default to 0) */
  42. static int16 pinglen;
  43.  
  44. /* Counter for generating seq numbers */
  45. static int16 iclk;
  46.  
  47. /* Increment counter -- called by low level clock tick */
  48. icmpclk()
  49. {
  50.     iclk++;
  51. }
  52.  
  53. /* Send ICMP Echo Request packets */
  54. doping(argc,argv)
  55. int argc;
  56. char *argv[];
  57. {
  58.     int32 dest;
  59.     struct ping *add_ping(),*pp1;
  60.     register struct ping *pp;
  61.     void ptimeout();
  62.     int16 hval,hash_ping();
  63.     int i;
  64.  
  65.     if(argc < 2){
  66.         printf("Host                Sent    Rcvd   %%   Avg RTT  Interval  Length\n");
  67.         for(i=0;i<PMOD;i++){
  68.             for(pp = ping[i];pp != NULLPING;pp = pp->next){
  69.                 printf("%-16s",inet_ntoa(pp->remote));
  70.                 printf("%8lu%8lu",pp->count,pp->echoes);
  71.                 printf("%4lu%10lu%10lu%8u\n",
  72.                  (long)pp->echoes * 100 / pp->count,
  73.                  pp->echoes != 0 ?
  74.                  TICK2MS(pp->ttotal) / pp->echoes : 0,
  75.                  TICK2SEC(pp->timer.start),pp->length);
  76.             }
  77.         }
  78.         return 0;
  79.     }
  80.     if(strcmp(argv[1],"clear") == 0){
  81.         for(i=0;i<PMOD;i++){
  82.             for(pp = ping[i];pp != NULLPING;pp = pp1){
  83.                 pp1 = pp->next;
  84.                 del_ping(pp);
  85.             }
  86.         }
  87.         return 0;
  88.     }
  89.     if(strcmp(argv[1],"length") == 0){
  90.         if(argc < 3)
  91.             printf("ping length %u\n",pinglen);
  92.         else
  93.             pinglen = atoi(argv[2]) % 4096;
  94.         return 0;
  95.     }
  96.     if((dest = resolve(argv[1])) == 0){
  97.         printf(badhost,argv[1]);
  98.         return 1;
  99.     }
  100.     /* See if dest is already in table */
  101.     hval = hash_ping(dest);
  102.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next){
  103.         if(pp->remote == dest){
  104.             break;
  105.         }
  106.     }
  107.     if(argc > 2){
  108.         /* Inter-ping time is specified; set up timer structure */
  109.         if(pp == NULLPING)
  110.             if ((pp = add_ping(dest)) == NULLPING){
  111.                 printf(nospace);
  112.                 return 1;
  113.             }
  114.         pp->timer.start = SEC2TICK(atol(argv[2]));
  115.         pp->timer.func = ptimeout;
  116.         pp->timer.arg = (char *)pp;
  117.         pp->remote = dest;
  118.         pp->length = (argc > 3)? (atoi(argv[3]) % 4096) : pinglen;
  119.         start_timer(&pp->timer);
  120.         pp->count++;
  121.         pingem(dest,iclk,REPEAT,pp->length);
  122.     } else
  123.         pingem(dest,iclk,ONESHOT,pinglen);
  124.  
  125.     return 0;
  126. }
  127.  
  128. /* Called by ping timeout */
  129. void
  130. ptimeout(p)
  131. char *p;
  132. {
  133.     register struct ping *pp;
  134.  
  135.     /* Send another ping */
  136.     pp = (struct ping *)p;
  137.     pp->count++;
  138.     pingem(pp->remote,iclk,REPEAT,pp->length);
  139.     start_timer(&pp->timer);
  140. }
  141. /* Send ICMP Echo Request packet */
  142. static
  143. pingem(dest,seq,id,len)
  144. int32 dest;
  145. int16 seq;
  146. int16 id;
  147. int16 len;
  148. {
  149.     struct mbuf *bp,*htonicmp();
  150.     struct mbuf *dbp = NULLBUF;
  151.     struct icmp icmp;
  152.     int i;
  153.     extern struct icmp_stats icmp_stats;
  154.  
  155.     if(len != 0){
  156.         if((dbp = alloc_mbuf(len)) == NULLBUF){
  157.             printf(nospace);
  158.             return 0;
  159.         }
  160.         for(i = 1; i <= len; i++)
  161.             dbp->data[i - 1] = uchar(i);
  162.         dbp->cnt = len;
  163.     }
  164.     icmp_stats.output[ECHO_REQ]++;
  165.     icmp.type = ECHO_REQ;
  166.     icmp.code = 0;
  167.     icmp.args.echo.seq = seq;
  168.     icmp.args.echo.id = id;
  169.     if((bp = htonicmp(&icmp,dbp)) == NULLBUF){
  170.         free_p(dbp);
  171.         return 0;
  172.     }
  173.     return ip_send(ip_addr,dest,ICMP_PTCL,0,0,bp,len_mbuf(bp),0,0);
  174. }
  175.  
  176. /* Called with incoming Echo Reply packet */
  177. int
  178. echo_proc(source,dest,icmp)
  179. int32 source,dest;
  180. struct icmp *icmp;
  181. {
  182.     register struct ping *pp;
  183.     int16 hval,hash_ping();
  184.     long rtt;
  185.  
  186.     if ((rtt = iclk - icmp->args.echo.seq) < 0)
  187.         rtt += 65536L;
  188.     hval = hash_ping(source);
  189.     for(pp = ping[hval]; pp != NULLPING; pp = pp->next)
  190.         if(pp->remote == source)
  191.             break;
  192.     if(pp == NULLPING || icmp->args.echo.id != 1){
  193.         printf("%s: echo reply id %u seq %u, %lu ms\n",
  194.          inet_ntoa(source),
  195.          icmp->args.echo.id,icmp->args.echo.seq,
  196.          TICK2MS(rtt));
  197.          fflush(stdout);
  198.     } else {
  199.         /* Repeated poll, just keep stats */
  200.         pp->ttotal += rtt;
  201.         pp->echoes++;
  202.     }
  203. }
  204. static
  205. int16
  206. hash_ping(dest)
  207. int32 dest;
  208. {
  209.     int16 hval;
  210.  
  211.     hval = (hiword(dest) ^ loword(dest)) % PMOD;
  212.     return hval;
  213. }
  214. /* Add entry to ping table */
  215. static
  216. struct ping *
  217. add_ping(dest)
  218. int32 dest;
  219. {
  220.     struct ping *pp;
  221.     int16 hval,hash_ping();
  222.  
  223.     pp = (struct ping *)calloc(1,sizeof(struct ping));
  224.     if(pp == NULLPING)
  225.         return NULLPING;
  226.  
  227.     hval = hash_ping(dest);
  228.     pp->prev = NULLPING;
  229.     pp->next = ping[hval];
  230.     if(pp->next != NULLPING)
  231.         pp->next->prev = pp;
  232.     ping[hval] = pp;
  233.     return pp;
  234. }
  235. /* Delete entry from ping table */
  236. static
  237. del_ping(pp)
  238. struct ping *pp;
  239. {
  240.     int16 hval,hash_ping();
  241.  
  242.     stop_timer(&pp->timer);
  243.  
  244.     if(pp->next != NULLPING)
  245.         pp->next->prev = pp->prev;
  246.     if(pp->prev != NULLPING) {
  247.         pp->prev->next = pp->next;
  248.     } else {
  249.         hval = hash_ping(pp->remote);
  250.         ping[hval] = pp->next;
  251.     }
  252.     free((char *)pp);
  253. }
  254. ə